#ifndef CLICKABLELABEL_H
#define CLICKABLELABEL_H

#include <QLabel>
#include <QMouseEvent>
#include <QPainter>
#include <QMargins>
#include <QPixmap>
#include <QPainterPath>

class ClickableLabel : public QLabel
{
    Q_OBJECT
public:
    // 三种模式
    enum class Mode{
        Button,                 // 按钮型（无状态保持）
        Selectable,             // 独立选择型（点击自动切换自身选中状态，如单选框）
        ExclusiveSelectable     // 互斥选择型（外部管理选中状态，如导航栏）
    };

    // 状态枚举（优先级：Pressed > Selected > Hovered > Default）
    enum class State{
        Default,   // 默认状态
        Hovered,   // 悬浮状态
        Pressed,   // 按下状态
        Selected   // 选中状态（仅选择型模式有效）
    };

    enum class Shape{
        Rectangle,//圆角矩形，可手动设置圆角半径
        Circle//圆形，可手动设置半径
    };

    enum class ContentAlignment{
        Left,   // 图片在左，文字在右
        Right,  // 图片在右，文字在左
        Top,    // 图片在上，文字在下
        Bottom  // 图片在下，文字在上
    };

    explicit ClickableLabel(QWidget* parent = nullptr,
                            Qt::WindowFlags f = Qt::WindowFlags());
    explicit ClickableLabel(const QString& text,
                            QWidget* parent = nullptr,
                            Qt::WindowFlags f = Qt::WindowFlags());

    template<typename Func>
    void inject(Func&& func) {
        std::forward<Func>(func)(*this);
    }

    void setMode(Mode mode);
    Mode getMode() const;

    void setSelected(bool selected);
    bool isSelected() const;

    // 设置选中状态的颜色（选择型模式用）
    void setSelectedColor(const QColor& color);
    QColor getSelectedColor() const;

    // 设置选中状态的Pixmap（选择型模式用）
    void setSelectedPixmap(const QPixmap& pixmap);

    void setDefaultPixmap(const QPixmap& pixmap);
    void setHoveredPixmap(const QPixmap& pixmap);
    void setPressedPixmap(const QPixmap& pixmap);

    // 手动设置当前状态（外部调用接口）
    void setCurrentState(State state);
    // 获取当前状态
    State getCurrentState() const;

    // 兼容原有接口：将setPixmap映射到"默认状态"的Pixmap
    void setPixmap(const QPixmap& pixmap) ;
    // 获取当前显示的Pixmap（根据当前状态）
    QPixmap getCurrentPixmap() const;

    // 设置默认状态颜色
    void setDefaultColor(const QColor& color);
    QColor getDefaultColor() const;

    // 设置按下状态颜色
    void setPressedColor(const QColor& color);
    QColor getPressedColor() const;

    // 设置悬浮状态颜色
    void setHoverColor(const QColor& color);
    QColor getHoverColor() const;

    // 设置形状
    void setShape(Shape shape);
    // 设置圆角半径（用于矩形）
    void setBorderRadius(int radius);
    // 设置半径（用于圆形）
    void setRadius(int radius);

    // 边距设置
    void setMargins(int left, int top, int right, int bottom);
    void setMargins(const QMargins& margins);
    QMargins getMargins() const;

    // 图片和文字间距设置
    void setPixmapTextSpacing(int spacing);
    int getPixmapTextSpacing() const;

    // 内容对齐方式
    void setContentAlignment(ContentAlignment alignment);
    ContentAlignment getContentAlignment() const;

    // 文本颜色设置
    void setTextColor(const QColor& color);
    QColor getTextColor() const;

signals:
    // 基础点击信号
    void clicked();
    // 带坐标参数的点击信号
    //void clicked(QPoint pos);
    // 带鼠标按键参数的点击信号
    //void clicked(Qt::MouseButton button);
    // 选中状态变化信号
    void selectedChanged(bool selected);

protected:
    // 鼠标事件处理
    virtual void mousePressEvent(QMouseEvent* event) override;
    virtual void mouseReleaseEvent(QMouseEvent* event) override;
    virtual void mouseMoveEvent(QMouseEvent* event) override;
    virtual void enterEvent(QEnterEvent* event) override;
    virtual void leaveEvent(QEvent* event) override;
    // 重绘事件
    virtual void paintEvent(QPaintEvent* event) override;

    virtual QSize minimumSizeHint() const override;

    // 检查点是否在形状内
    bool isPointInShape(const QPoint& point) const;

private:
    // 计算内容所需的最小尺寸
    QSize calculateContentMinimumSize(const QFontMetrics& fontMetrics,
                                      State currentState,
                                      int spacing,
                                      ContentAlignment alignment) const;

    // 形状模板类，实现静态多态
    template<Shape S>
    struct ShapeDrawer {
        static void draw(QPainter& painter, const QRect& rect, int radius,
                         const QString& text, const QColor& textColor,
                         const QPixmap& currentPixmap,
                         int pixmapTextSpacing,
                         const QMargins& margins, ContentAlignment alignment);
        static bool contains(const QRect& rect, int radius, const QPoint& point);
    };

    // 成员变量
    Mode m_mode;                  // 当前模式（按钮型/选择型）
    bool m_selected;              // 是否选中（仅选择型模式有效）
    State m_currentState;         // 当前状态
    Shape m_shape;                // 当前形状
    QColor m_defaultColor;        // 默认状态颜色
    QColor m_pressedColor;        // 按下状态颜色
    QColor m_hoverColor;          // 悬浮状态颜色
    QColor m_selectedColor;       // 选中状态颜色（选择型模式用）

    int m_borderRadius;           // 圆角半径
    int m_radius;                 // 圆形半径
    QMargins m_margins;           // 边距
    int m_pixmapTextSpacing;      // 图片和文字间距
    ContentAlignment m_alignment; // 内容对齐方式
    QColor m_textColor;           // 文本颜色

    // 四种状态的Pixmap
    QPixmap m_defaultPixmap;
    QPixmap m_hoveredPixmap;
    QPixmap m_pressedPixmap;
    QPixmap m_selectedPixmap;     // 选中状态的Pixmap（选择型模式用）
};

// 矩形形状特化
template<>
struct ClickableLabel::ShapeDrawer<ClickableLabel::Shape::Rectangle> {
    static void draw(QPainter& painter, const QRect& rect, int radius,
                     const QString& text, const QColor& textColor,
                     const QPixmap& currentPixmap,
                     int pixmapTextSpacing,
                     const QMargins& margins, ContentAlignment alignment) {
        painter.setRenderHint(QPainter::Antialiasing);
        // 绘制圆角矩形
        painter.drawRoundedRect(rect.adjusted(1, 1, -1, -1), radius, radius);

        // 计算内容区域（考虑边距）
        QRect contentRect = rect.adjusted(
            margins.left(),
            margins.top(),
            -margins.right(),
            -margins.bottom()
            );

        // 确保内容区域有效
        if (contentRect.width() <= 0 || contentRect.height() <= 0)
            return;

        // 保存当前画家状态并设置裁剪区域
        painter.save();
        painter.setClipRect(contentRect);

        // 绘制内容（图片和文字）
        drawContent(painter, contentRect, text, textColor, currentPixmap,
                    pixmapTextSpacing, alignment);

        // 恢复画家状态
        painter.restore();
    }

    static bool contains(const QRect& rect, int radius, const QPoint& point) {
        return rect.contains(point);
    }

    // 绘制图片和文字内容
    static void drawContent(QPainter& painter, const QRect& rect, const QString& text,
                            const QColor& textColor, const QPixmap& currentPixmap,
                            int spacing, ContentAlignment alignment) {
        bool hasPixmap = !currentPixmap.isNull();
        bool hasText = !text.isEmpty();

        if (!hasPixmap && !hasText) return;

        // 设置文本颜色
        painter.setPen(textColor);
        QFontMetrics fontMetrics = painter.fontMetrics();

        if (hasPixmap && hasText) {
            // 既有图片又有文字
            if (alignment == ClickableLabel::ContentAlignment::Left ||
                alignment == ClickableLabel::ContentAlignment::Right) {
                // 水平排列
                int totalWidth = currentPixmap.width() + spacing + fontMetrics.horizontalAdvance(text);
                int totalHeight = qMax(currentPixmap.height(), fontMetrics.height());

                // 确保内容不会超出边界
                int x = rect.center().x() - totalWidth / 2;
                x = qMax(rect.left(), qMin(x, rect.right() - totalWidth));
                int y = rect.center().y() - totalHeight / 2;

                // 水平排列时的文字绘制
                if (alignment == ClickableLabel::ContentAlignment::Left) {
                    // 绘制图片
                    painter.drawPixmap(x, y, currentPixmap);

                    // 计算文字的垂直居中位置
                    int textY = y + (totalHeight - fontMetrics.height()) / 2 + fontMetrics.ascent();
                    painter.drawText(x + currentPixmap.width() + spacing, textY, text);
                } else {
                    // 绘制文字（右侧对齐时同理）
                    int textY = y + (totalHeight - fontMetrics.height()) / 2 + fontMetrics.ascent();
                    painter.drawText(x, textY, text);

                    // 绘制图片
                    painter.drawPixmap(x + fontMetrics.horizontalAdvance(text) + spacing, y, currentPixmap);
                }
            } else {
                // 垂直排列
                int totalHeight = currentPixmap.height() + spacing + fontMetrics.height();
                int totalWidth = qMax(currentPixmap.width(), fontMetrics.horizontalAdvance(text));
                int x = rect.center().x() - totalWidth / 2;
                int y = rect.center().y() - totalHeight / 2;

                y = qMax(rect.top(), qMin(y, rect.bottom() - totalHeight));

                if (alignment == ClickableLabel::ContentAlignment::Top) {
                    painter.drawPixmap(x + (totalWidth - currentPixmap.width()) / 2, y, currentPixmap);
                    painter.drawText(rect.adjusted(0, y + currentPixmap.height() + spacing, 0, 0),
                                     Qt::AlignHCenter, text);
                } else {
                    painter.drawText(rect.adjusted(0, y, 0, -(currentPixmap.height() + spacing)),
                                     Qt::AlignHCenter | Qt::AlignBottom, text);
                    painter.drawPixmap(x + (totalWidth - currentPixmap.width()) / 2,
                                       y + fontMetrics.height() + spacing, currentPixmap);
                }
            }
        } else if (hasPixmap) {
            // 只有图片 - 确保图片在内容区域内
            int x = rect.center().x() - currentPixmap.width() / 2;
            int y = rect.center().y() - currentPixmap.height() / 2;

            x = qMax(rect.left(), qMin(x, rect.right() - currentPixmap.width()));
            y = qMax(rect.top(), qMin(y, rect.bottom() - currentPixmap.height()));

            painter.drawPixmap(x, y, currentPixmap);
        } else {
            // 只有文字
            painter.drawText(rect, Qt::AlignCenter, text);
        }
    }
};

// 圆形形状特化
template<>
struct ClickableLabel::ShapeDrawer<ClickableLabel::Shape::Circle> {
    static void draw(QPainter& painter, const QRect& rect, int radius,
                     const QString& text, const QColor& textColor,
                     const QPixmap& currentPixmap,
                     int pixmapTextSpacing,
                     const QMargins& margins, ContentAlignment alignment) {
        painter.setRenderHint(QPainter::Antialiasing);
        int actualRadius = qMin(radius, qMin(rect.width(), rect.height()) / 2);
        // 绘制圆形
        painter.drawEllipse(rect.center(), actualRadius, actualRadius);

        // 计算最大边距
        int maxMargin1 = qMax(margins.left(), margins.top());
        int maxMargin2 = qMax(margins.right(), margins.bottom());
        int maxMargin = qMax(maxMargin1, maxMargin2);
        int contentRadius = qMax(actualRadius - maxMargin, 0);

        // 计算内容区域（圆形内的正方形区域）
        QRect contentRect = QRect(
            rect.center().x() - contentRadius,
            rect.center().y() - contentRadius,
            2 * contentRadius,
            2 * contentRadius
            );

        // 绘制内容（图片和文字）
        drawContent(painter, contentRect, text, textColor, currentPixmap,
                    pixmapTextSpacing, alignment);
    }

    static bool contains(const QRect& rect, int radius, const QPoint& point) {
        QPoint center = rect.center();
        int actualRadius = qMin(radius, qMin(rect.width(), rect.height()) / 2);
        int dx = point.x() - center.x();
        int dy = point.y() - center.y();
        return (dx * dx + dy * dy) <= (actualRadius * actualRadius);
    }

    // 绘制图片和文字内容（复用矩形的实现）
    static void drawContent(QPainter& painter, const QRect& rect, const QString& text,
                            const QColor& textColor, const QPixmap& currentPixmap,
                            int spacing, ContentAlignment alignment) {
        ClickableLabel::ShapeDrawer<ClickableLabel::Shape::Rectangle>::drawContent(
            painter, rect, text, textColor, currentPixmap, spacing, alignment
            );
    }
};

#endif // CLICKABLELABEL_H
